#include <iostream>
#include <vector>
#include <sstream>
#include <fstream>
#include <cmath>
#include <cstdlib>

#include <algorithm>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <string.h>
#include <unordered_map>

using namespace std;

string testFile = "/data/test_data.txt";
string resultFile = "/projects/student/result.txt";

int node_num = 0;
typedef uint account;
typedef vector<account> Loop;
typedef vector<Loop> Loops;
Loops loops3, loops4, loops5, loops6, loops7;

vector<account> inputs;
vector<account> nodes;
unordered_map<account, int> idHash;
vector<vector<int>> G;
vector<int> from;
vector<int> to;


inline unsigned int parse(char** s){
	char *p = *s;
	unsigned int val = *(p++) - '0';
	while(*p != ','){
		val = 10*val + *(p++) - '0';
	}
	*s = p+1;
	return val;
}
void loadData_and_createGrap(){
	int fd = open(testFile.c_str(), O_RDONLY);
    int file_size = lseek(fd, 0, SEEK_END);
    char* p_map =(char*)mmap(NULL, file_size, PROT_READ, MAP_PRIVATE, fd, 0);
    close(fd);
	char *p = p_map;
	account a1,a2;
	while(*p != '\0'){
		a1 = parse(&p);
		a2 = parse(&p);
		inputs.emplace_back(a1);
		inputs.emplace_back(a2);
		while(*p != '\n') p++;
		p++;
	}
	nodes = inputs;
	sort(nodes.begin(),nodes.end());//排序
	nodes.erase(unique(nodes.begin(),nodes.end()),nodes.end());//去重
	for(uint& v:nodes) idHash[v] = node_num++;
	G = vector<vector<int>>(node_num);
	int v,u;
	for(int i=0; i<inputs.size(); i+=2){
		v = idHash[inputs[i]];
		u = idHash[inputs[i+1]];
		G[v].emplace_back(u);
		from.emplace_back(v);
		to.emplace_back(u);
	}
	for(int i=0; i<node_num; i++) sort(G[i].begin(),G[i].end());
	munmap(p_map, file_size);
}

char buf[77*3*1000000];
char* p = buf;

void uint_to_char(const Loop& loop){
	string tmp = to_string(loop[0]);
	int size = tmp.size();
	memcpy(p, tmp.c_str(), size);
	p += size;
	for(int i=1; i<loop.size(); i++){
		tmp = to_string(loop[i]);
		size = tmp.size();
		*(p++) = ',';
		memcpy(p, tmp.c_str(), size);
		p += size;
	}
	*(p++) = '\n';
}

void save(){
	int num = loops3.size()+loops4.size()+loops5.size()+loops6.size()+loops7.size();
	string tmp = to_string(num);
	int size = tmp.size();
	memcpy(p, tmp.c_str(), size);
	p += size;
	*(p++) = '\n';
	for(auto& loop:loops3) uint_to_char(loop);
	for(auto& loop:loops4) uint_to_char(loop);
	for(auto& loop:loops5) uint_to_char(loop);
	for(auto& loop:loops6) uint_to_char(loop);
	for(auto& loop:loops7) uint_to_char(loop);
	int data_size = p - buf;
	int fd = open(resultFile.c_str(), O_RDWR|O_CREAT, 0666);
	ftruncate(fd, data_size);
	char* p_map =(char*)mmap(NULL, data_size, PROT_WRITE, MAP_SHARED, fd, 0);
	memcpy(p_map, buf, data_size);
	munmap(p_map, data_size);
	close(fd);
}

int main(int argc, char* argv[]){
	loadData_and_createGrap();
	vector<int> uSet2, uSet3, uSet4, uSet5, uSet6;
	for(int u=0; u<node_num; u++){
		for(int& v1:G[u]){
			if(v1 < u) continue;
			for(int& v2:G[v1]) {
				if(v2 > u) uSet2.emplace_back(v2);
			}
			for(int& v2:uSet2){
				for(int& v3:G[v2]){
					if(v3 > u && v3!=v1) uSet3.emplace_back(v3);
					else if(v3 == u){
						Loop lp;
						lp.emplace_back(nodes[u]);
						lp.emplace_back(nodes[v1]);
						lp.emplace_back(nodes[v2]);
						loops3.emplace_back(lp);
					}
				}
				for(int& v3:uSet3){
					for(int& v4:G[v3]){
						if(v4 > u && v4!=v2 && v4!=v1) uSet4.emplace_back(v4);
						else if(v4 == u){
							Loop lp;
							lp.emplace_back(nodes[u]);
							lp.emplace_back(nodes[v1]);
							lp.emplace_back(nodes[v2]);
							lp.emplace_back(nodes[v3]);
							loops4.emplace_back(lp);
						}
					}
					for(int& v4:uSet4){
						for(int& v5:G[v4]){
							if(v5 > u && v5!=v3 && v5!=v2 && v5!=v1) uSet5.emplace_back(v5);
							else if(v5 == u){
								Loop lp;
								lp.emplace_back(nodes[u]);
								lp.emplace_back(nodes[v1]);
								lp.emplace_back(nodes[v2]);
								lp.emplace_back(nodes[v3]);
								lp.emplace_back(nodes[v4]);
								loops5.emplace_back(lp);
							}
						}
						for(int& v5:uSet5){
							for(int& v6:G[v5]){
								if(v6 > u && v6!=v4 && v6!=v3 && v6!=v2 && v6!=v1) uSet6.emplace_back(v6);
								else if(v6 == u){
									Loop lp;
									lp.emplace_back(nodes[u]);
									lp.emplace_back(nodes[v1]);
									lp.emplace_back(nodes[v2]);
									lp.emplace_back(nodes[v3]);
									lp.emplace_back(nodes[v4]);
									lp.emplace_back(nodes[v5]);
									loops6.emplace_back(lp);
								}
							}
							for(int& v6:uSet6){
								for(int& v7:G[v6]){
									if(v7 == u){
										Loop lp;
										lp.emplace_back(nodes[u]);
										lp.emplace_back(nodes[v1]);
										lp.emplace_back(nodes[v2]);
										lp.emplace_back(nodes[v3]);
										lp.emplace_back(nodes[v4]);
										lp.emplace_back(nodes[v5]);
										lp.emplace_back(nodes[v6]);
										loops7.emplace_back(lp);
										break;
									}
								}
							}
							uSet6.clear();
						}
						uSet5.clear();
					}
					uSet4.clear();
				}
				uSet3.clear();
			}
			uSet2.clear();
		}
	}
	save();
	return 0;
}